package com.zjmzxfzhl.modules.purchase.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IoUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zjmzxfzhl.common.base.BaseServiceImpl;
import com.zjmzxfzhl.common.exception.AppException;
import com.zjmzxfzhl.common.util.PathUtil;
import com.zjmzxfzhl.common.util.bs.PurchaseUtils;
import com.zjmzxfzhl.modules.purchase.controller.dto.PurchaseOrderDetailDto;
import com.zjmzxfzhl.modules.purchase.controller.dto.PurchaseOrderDetailUpdateDto;
import com.zjmzxfzhl.modules.purchase.controller.dto.PurchaseOrderDto;
import com.zjmzxfzhl.modules.purchase.controller.dto.PurchaseOrderUpdateDto;
import com.zjmzxfzhl.modules.purchase.controller.vo.PurchaseOrderDetailVo;
import com.zjmzxfzhl.modules.purchase.controller.vo.PurchaseOrderVo;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseContract;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseIndent;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseMaterial;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseOrder;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseOrderDetail;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseProject;
import com.zjmzxfzhl.modules.purchase.entity.PurchaseSupplier;
import com.zjmzxfzhl.modules.purchase.mapper.PurchaseOrderMapper;
import com.zjmzxfzhl.modules.purchase.service.PurchaseContractService;
import com.zjmzxfzhl.modules.purchase.service.PurchaseIndentService;
import com.zjmzxfzhl.modules.purchase.service.PurchaseMaterialService;
import com.zjmzxfzhl.modules.purchase.service.PurchaseOrderDetailService;
import com.zjmzxfzhl.modules.purchase.service.PurchaseOrderService;
import com.zjmzxfzhl.modules.purchase.service.PurchaseProjectService;
import com.zjmzxfzhl.modules.purchase.service.PurchaseSupplierService;
import com.zjmzxfzhl.modules.purchase.service.bo.PurchaseOrderExcelBo;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Service
 *
 * @author 庄金明
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class PurchaseOrderServiceImpl extends BaseServiceImpl<PurchaseOrderMapper, PurchaseOrder>
        implements PurchaseOrderService {


    @Autowired
    private PurchaseMaterialService materialService;

    @Autowired
    private PurchaseSupplierService supplierService;

    @Autowired
    private PurchaseOrderDetailService detailService;

    @Autowired
    private PurchaseProjectService projectService;

    @Autowired
    private PurchaseIndentService indentService;

    @Autowired
    private PurchaseContractService contractService;


    @Override
    public IPage<PurchaseOrderVo> list(IPage<PurchaseOrderVo> page, PurchaseOrderDto purchaseOrder) {
        return page.setRecords(baseMapper.list(page, purchaseOrder));
    }

    @Override
    public void upload(MultipartFile multipartFile) {
        try {
            //获取文件
            File targetFile = PathUtil.getTempFile(multipartFile.getOriginalFilename());
            BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(targetFile));
            IoUtil.write(stream, true, multipartFile.getBytes());

            //读取文件内容
            Map<PurchaseOrder, List<PurchaseOrderExcelBo>> orderMap = PurchaseUtils.readPurchaseOrder(targetFile);

            for (Map.Entry<PurchaseOrder, List<PurchaseOrderExcelBo>> entry : orderMap.entrySet()) {
                List<PurchaseOrderDetailUpdateDto> orderDetailUpdateDtos = new ArrayList<>();
                for (PurchaseOrderExcelBo excelBo : entry.getValue()) {
                    orderDetailUpdateDtos.add(new PurchaseOrderDetailUpdateDto(excelBo));
                }
                disposePurchaseOrderExcel(entry.getKey(), orderDetailUpdateDtos, true);
            }
            contractService.genContract();
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new AppException("导入采购审批单失败：" + e.getMessage());
        }


    }


    public void disposePurchaseOrderExcel(PurchaseOrder order, List<PurchaseOrderDetailUpdateDto> validInfos, boolean checkMaterialTotalPrice) {
        try {
            if (CollectionUtils.isEmpty(validInfos)) {
                throw new AppException("审批单：" + order.getOrderCode() + " 未找到有效信息");
            }
            BigDecimal orderTotalPrice = new BigDecimal(0);

            for (PurchaseOrderDetailUpdateDto orderDetail : validInfos) {
                //校验物料总价
                BigDecimal total = orderDetail.getUnitPrice().multiply(orderDetail.getMaterialNum());
                if (checkMaterialTotalPrice &&
                        null != orderDetail.getMaterialTotalPrice() &&
                        orderDetail.getMaterialTotalPrice().compareTo(total) != 0) {
                    throw new AppException(MessageFormat.format("设备:{0}-总价不等于单价*数量:{1}={2}*{3}",
                            orderDetail.getMaterialName(),
                            orderDetail.getMaterialTotalPrice(),
                            orderDetail.getUnitPrice(),
                            orderDetail.getMaterialNum()));
                }
                orderTotalPrice = orderTotalPrice.add(total);

            }
            //审批单编码唯一性校验
            PurchaseOrder filter = new PurchaseOrder();
            filter.setOrderCode(order.getOrderCode());
            List<PurchaseOrder> purchaseOrders = this.list(new QueryWrapper<>(filter));
            if (!CollectionUtils.isEmpty(purchaseOrders)) {
                if (purchaseOrders.size() > 1) {
                    throw new AppException("审批单编码已存在：" + order.getOrderCode());
                } else if (order.getId() == null || !purchaseOrders.get(0).getId().equals(order.getId())) {
                    throw new AppException("审批单编码已存在：" + order.getOrderCode());
                }
            }

            //插入或更新 order
            order.setPrice(orderTotalPrice);
            this.saveOrUpdate(order);
            List<PurchaseOrderDetailVo> deleteDetails = null;
            if (null != order.getId()) {
                //查询待删除的详情记录
                PurchaseOrderDetailDto detailFilter = new PurchaseOrderDetailDto();
                detailFilter.setOrderId(order.getId());
                deleteDetails = detailService.listBy(detailFilter);
            }
            for (PurchaseOrderDetailUpdateDto orderDetailDto : validInfos) {
                PurchaseMaterial material = orderDetailDto.genMaterialEntity();
                //判断是否存在该物料，如果没有则添加
                PurchaseMaterial dbMaterial = materialService.validPurchaseMaterial(material);

                PurchaseSupplier supplier = orderDetailDto.genSupplierEntity();

                PurchaseSupplier dbSupplier = supplierService.validPurchaseSupplier(supplier);

                //校验采购订单
                PurchaseIndent indent = orderDetailDto.genIndentEntity();
                PurchaseIndent dbIndent = indentService.validPurchaseIndent(indent);
                if (!StringUtils.isEmpty(orderDetailDto.getContractCode())) {
                    PurchaseContract dbContract = contractService.validPurchaseContract(orderDetailDto.genContractEntity());
                    dbIndent.setContractId(dbContract.getId());
                    indentService.updateById(dbIndent);
                }

                PurchaseProject project = orderDetailDto.genProjectEntity();
                PurchaseProject dbProject = projectService.validPurchaseProject(project);

                PurchaseOrderDetail orderDetail = new PurchaseOrderDetail();

                orderDetail.setMaterialId(dbMaterial.getId());
                orderDetail.setOrderId(order.getId());
                orderDetail.setSupplierId(dbSupplier.getId());
                orderDetail.setMaterialNum(orderDetailDto.getMaterialNum());
                orderDetail.setIndentId(dbIndent.getId());
                orderDetail.setProjectId(dbProject.getId());
                detailService.save(orderDetail);
            }
            //删除旧详情记录
            if (!CollectionUtils.isEmpty(deleteDetails)) {
                detailService.removeByIds(deleteDetails.stream().map(PurchaseOrderDetailVo::getId).collect(Collectors.toList()));
            }
        } catch (Exception ex) {
            throw new AppException("审批单-" + order.getOrderCode() + "," + ex.getMessage());
        }

    }

    @Override
    public void deleteByIds(String[] ids) {
        for (String id : ids) {
            Long orderId = Long.valueOf(id);
            detailService.deleteByOrderId(orderId);
            this.removeById(orderId);
        }
    }

    @Override
    public void updateUnitPrice(Long orderId, Long materialId, BigDecimal unitPrice) {
        //查询原始价格
        PurchaseMaterial dbMaterial = materialService.getById(materialId);
        if (null == dbMaterial) {
            throw new AppException("设备ID：" + materialId + " 不存在");
        }
        PurchaseOrder order = this.getById(orderId);
        if (order == null) {
            throw new AppException("设备审批单" + orderId + "不存在");
        }
        PurchaseOrderDetail detailFilter = new PurchaseOrderDetail();
        detailFilter.setOrderId(orderId);
        detailFilter.setMaterialId(materialId);
        List<PurchaseOrderDetail> assoDetails = detailService.list(new QueryWrapper<>(detailFilter));
        if (CollectionUtils.isEmpty(assoDetails) || assoDetails.size() > 1) {
            throw new AppException("未找到或找到多条审批清单");
        }

        if (unitPrice.floatValue() == dbMaterial.getUnitPrice().floatValue()) {
            return;
        }
        BigDecimal oldUnitPrice = dbMaterial.getUnitPrice();
        dbMaterial.setUnitPrice(unitPrice);
        List<PurchaseOrderDetail> otherDetails = detailService.listMaterialNotInOrder(materialId, orderId);

        if (CollectionUtils.isEmpty(otherDetails)) {
            //直接更新价格
            materialService.updateById(dbMaterial);

        } else {
            PurchaseMaterial filter = new PurchaseMaterial();
            filter.setMaterialCode(dbMaterial.getMaterialCode());
            filter.setMaterialName(dbMaterial.getMaterialName());
            filter.setMaterialSpecification(dbMaterial.getMaterialSpecification());
            List<PurchaseMaterial> purchaseMaterials = materialService.list(new QueryWrapper<>(filter));

            dbMaterial = materialService.findOrInsert(purchaseMaterials, dbMaterial);
            //更新关联的detail
            for (PurchaseOrderDetail orderDetail : assoDetails) {
                orderDetail.setMaterialId(dbMaterial.getId());
                detailService.updateById(orderDetail);
            }
        }

        //更新审批单总价
        order.setPrice(order.getPrice().subtract((oldUnitPrice.subtract(unitPrice)).multiply(assoDetails.get(0).getMaterialNum())));
        this.updateById(order);


    }


    @Override
    public File export(Long orderId) {
        //查询所有相关内容
        PurchaseOrder order = this.getById(orderId);
        PurchaseOrderDetailDto filter = new PurchaseOrderDetailDto();
        filter.setOrderId(orderId);
        List<PurchaseOrderDetailVo> orderDetails = detailService.listBy(filter);
        List<PurchaseOrderExcelBo> excelBos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(orderDetails)) {
            int xh = 1;
            for (PurchaseOrderDetailVo detailVo : orderDetails) {
                PurchaseOrderExcelBo excelBo = new PurchaseOrderExcelBo(xh, detailVo);
                excelBos.add(excelBo);
                xh++;
            }
        }
        File exportFile = null;
        try {
            ClassPathResource templateFileResource = new ClassPathResource("templates/order-template.xls");
            exportFile = PathUtil.getTempFile("设备审批单_" + order.getOrderCode() + "_.xls");
            FileUtils.copyInputStreamToFile(templateFileResource.getInputStream(), exportFile);
            PurchaseUtils.exportPurchaseOrder(order, excelBos, exportFile);
        } catch (Exception e) {
            throw new AppException("文件读取失败" + e.getMessage());
        }
        return exportFile;

    }

    @Override
    public boolean addOrUpdateOrder(PurchaseOrderUpdateDto orderDto) {
        PurchaseOrder order = BeanUtil.copyProperties(orderDto, PurchaseOrder.class);
        disposePurchaseOrderExcel(order, orderDto.getDetails(), false);
        contractService.genContract();
        return true;
    }
}
